package com.h3bpm.starcharge.controller;


import OThinker.Common.DotNetToJavaStringHelper;
import OThinker.Common.Organization.Models.OrganizationUnit;
import OThinker.Common.Organization.Models.User;
import OThinker.H3.Controller.ControllerBase;
import OThinker.H3.Entity.DataModel.BizObject;
import OThinker.H3.Entity.DataModel.BizObjectSchema;
import OThinker.H3.Entity.Instance.Data.IInstanceDataItem;
import OThinker.H3.Entity.Instance.Data.InstanceData;
import OThinker.H3.Entity.Instance.InstanceContext;
import OThinker.H3.Entity.Instance.PriorityType;
import OThinker.H3.Entity.Instance.Token;
import OThinker.H3.Entity.Messages.ActivateInstanceMessage;
import OThinker.H3.Entity.Messages.Instance.StartInstanceMessage;
import OThinker.H3.Entity.Messages.MessageEmergencyType;
import OThinker.H3.Entity.WorkflowTemplate.WorkflowDocument.PublishedWorkflowTemplate;
import OThinker.H3.Entity.WorkflowTemplate.WorkflowDocument.PublishedWorkflowTemplateHeader;
import api.APIController;
import api.domain.contract.create.CreateContractVO;
import api.domain.contract.download.DownloadFileVo;
import api.domain.contract.returnvo.ContractMessageType;
import api.domain.contract.returnvo.ReturnVO;
import api.domain.contract.sign.SignContractVO;
import api.domain.contract.sign.Signer;
import api.domain.preview.PreviewVO;
import api.domain.template.create.SendContractsSyncVO;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.h3bpm.base.util.AppUtility;
import com.h3bpm.starcharge.common.bean.Bestsign_file;
import com.h3bpm.starcharge.common.bean.RetResponse;
import com.h3bpm.starcharge.common.bean.RetResult;
import com.h3bpm.starcharge.common.uitl.*;
import com.h3bpm.starcharge.common.uitl.bestsign.CreateContractParam;
import com.h3bpm.starcharge.common.uitl.bestsign.CreateContractsSyncParam;
import com.h3bpm.starcharge.service.ems.DocumentPushService;
import data.DataTable;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;

@Controller
@RequestMapping("/starCharge/bestsignController")
public class BestsignController extends ControllerBase {

    private static APIController apiController = new APIController();

    static Logger logger = Logger.getLogger(ControllerBase.class);

    private final static List<String> BASEDTO = Arrays.asList("CreatedBy", "CreatedTime", "ObjectID", "ModifiedBy", "Name", "OwnerId", "ModifiedTime", "CreatedByParentId", "OwnerParentId", "RunningInstanceId","ContractId","contractId");

    private final ObjectMapper mapper = new ObjectMapper();

    private static String QueryInstanceIdByContractId = BestsignPropertiesUtil.getProperty("queryInstanceIdByContractId");

    private static final String ACCOUNT = BestsignPropertiesUtil.getProperty("account");


    @Autowired
    private DocumentPushService documentPushService;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public String getFunctionCode() {
        return null;
    }

    /**
     * 1 提交前预览
     */
    @RequestMapping(value = "/preview", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    @ResponseBody
    public void preview(String instanceId, HttpServletResponse response) {

        if (DotNetToJavaStringHelper.isNullOrEmpty(instanceId)) {
            //return null;
        }
        try {
            InstanceData instanceData = new InstanceData(getEngine(), instanceId, User.AdministratorID);
            SendContractsSyncVO sendContractsSyncVO = CreateContractsSyncParam.createParam(instanceData);
            PreviewVO previewVO = new PreviewVO();
            previewVO.setTemplateId(sendContractsSyncVO.getTemplateId());
            previewVO.setTextLabels(sendContractsSyncVO.getPlaceHolders().get(0).getTextLabels());
            Bestsign_file bestsignFile = apiController.preview(instanceId, previewVO);
            response.setCharacterEncoding("UTF-8");
            response.setContentType(bestsignFile.getFileType());
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(bestsignFile.getFileName(), "UTF-8"));
            response.addHeader("Content-Type", bestsignFile.getFileType());
            response.flushBuffer();
            response.getOutputStream().write(bestsignFile.getContent());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 2.1 非标提交合同
     * 返回 上上签合同编号
     */
    @RequestMapping(value = "/createContract", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    @ResponseBody
    public Object createContract(String instanceId) {
        String contractId = "";
        Map<String, String> resultMap = new HashMap<>(1);

        if (DotNetToJavaStringHelper.isNullOrEmpty(instanceId) || DotNetToJavaStringHelper.isNullOrEmpty(instanceId)) {
            return null;
        }
        try {
            InstanceData instanceData = new InstanceData(getEngine(), instanceId, User.AdministratorID);
            contractId = apiController.createContract(CreateContractParam.createParam(instanceData));
            IInstanceDataItem iInstanceDataItem = instanceData.getItem("contractId");
            iInstanceDataItem.setValue(contractId);
            instanceData.Submit();
        } catch (Exception e) {
            e.printStackTrace();
        }
        resultMap.put("contractId", contractId);
        //此时 调用提交后预览，将 contractId 和 instanceId关系存入数据库
        previewAfterNoDown(instanceId, contractId);
        return resultMap;
    }

    /**
     * 2.2 标准提交合同
     * 返回 上上签合同编号
     *
     * @param instanceId
     * @return
     */
    @RequestMapping(value = "/sendContractsSync", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    @ResponseBody
    public Object sendContractsSync(String instanceId) {
        String contractId = "";
        Map<String, String> resultMap = new HashMap<>(1);

        if (DotNetToJavaStringHelper.isNullOrEmpty(instanceId) || DotNetToJavaStringHelper.isNullOrEmpty(instanceId)) {
            return null;
        }
        try {
            InstanceData instanceData = new InstanceData(getEngine(), instanceId, User.AdministratorID);
            contractId = apiController.sendContractsSync(CreateContractsSyncParam.createParam(instanceData));
        } catch (Exception e) {
            e.printStackTrace();
        }
        resultMap.put("contractId", contractId);

        //此时 调用提交后预览，将 contractId 和 instanceId关系存入数据库
        previewAfterNoDown(instanceId, contractId);
        return resultMap;
    }


    /**
     * 3.0 提交后预览，传上上签合同id
     *
     * @param contractId
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/previewAfterNoDown", method = {RequestMethod.GET, RequestMethod.POST}, produces = "application/json;charset=utf-8")
    @ResponseBody
    public Object previewAfterNoDown(String instanceId, String contractId) {
        try {
            Bestsign_file bestsignFile = APIController.queryFile(instanceId, "previewAfter");
            if (null == bestsignFile) {
                apiController.previewAfter(instanceId, contractId);
            } else {
                // 当 instanceId 存在 合同  而 两次contractId 又不一致，说明合同有更新。需要先删除再重新插入
                if (!bestsignFile.getContractId().equals(contractId)) {
                    APIController.deleteFile(instanceId);
                    apiController.previewAfter(instanceId, contractId);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 3 提交后预览，传上上签合同id
     *
     * @param contractId
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/previewAfter", method = {RequestMethod.GET, RequestMethod.POST}, produces = "application/json;charset=utf-8")
    @ResponseBody
    public Object previewAfter(String instanceId, String contractId, HttpServletResponse response) {
        try {
            Bestsign_file bestsignFile = APIController.queryFile(instanceId, "previewAfter");
            if (null == bestsignFile) {
                bestsignFile = apiController.previewAfter(instanceId, contractId);
            }
            response.setCharacterEncoding("UTF-8");
            response.setContentType(bestsignFile.getFileType());
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(bestsignFile.getFileName(), "UTF-8"));
            response.addHeader("Content-Type", bestsignFile.getFileType());
            response.flushBuffer();
            response.getOutputStream().write(bestsignFile.getContent());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }


    /**
     * 4 签名，盖章
     *
     * @param contractId
     */
    @RequestMapping(value = "/sign", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    @ResponseBody
    public void sign(String contractId, String sealName, String company) {
        SignContractVO signContractVO = new SignContractVO();
        signContractVO.setSigner(new Signer(ACCOUNT, company));
        signContractVO.setSealName(sealName);
        List<Long> contractIds = Arrays.asList(Long.parseLong(contractId));
        signContractVO.setContractIds(contractIds);
        apiController.sign(signContractVO);
    }

    /**
     * @param contractId
     */
    @RequestMapping(value = "/signOnly", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    @ResponseBody
    public void signOnly(String contractId) {
        SignContractVO signContractVO = new SignContractVO();
        signContractVO.setSigner(new Signer("starcharge.dehe@wanbangauto.com", "万帮充电设备有限公司"));
        signContractVO.setSealName("万帮充电合同章");
        List<Long> contractIds = Arrays.asList(Long.parseLong(contractId));
        signContractVO.setContractIds(contractIds);
        apiController.sign(signContractVO);
        //System.out.println( string);
    }

    /**
     * 合同完成回调
     */
    @RequestMapping(value = "/contractFinish", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    @ResponseBody
    public Object contractFinish(@RequestBody String resultStr) throws Exception {
        logger.info("==contractFinish====" + resultStr);
        try {
            Map<String, Object> resultMap = mapper.readValue(resultStr, Map.class);
            String type = (String) resultMap.get("type");
            if (ContractMessageType.CONTRACT_COMPLETE.name().equals(type)) {
                List<Long> contractIds = (List<Long>) ((Map<String, Object>) resultMap.get("responseData")).get("contractIds");
                for (Long contractId : contractIds) {
                    String cId = String.valueOf(contractId);
                    //现根据合同id查流程id，提交合同必生成预览后数据
                    DataTable dataTable = SqlUtils.doQuery(String.format(QueryInstanceIdByContractId, contractId, "previewAfter"));
                    if (dataTable.getRows().size() > 0) {
                        String instanceId = dataTable.getRows().get(0).getString(0);
                        Bestsign_file bestsignFile = APIController.queryFile(instanceId, "download");
                        if (null == bestsignFile) {
                            bestsignFile = apiController.downloadFile(instanceId, cId, new DownloadFileVo(Arrays.asList(cId)));
                            documentPushService.postFileToEMS(bestsignFile);
                            return new ReturnVO<String>("0", "success", null);
                        }
                    }
                }
            } else if (ContractMessageType.OPERATION_COMPLETE.name().equals(type)) {
                //只要有一方签署，更改状态，跳出等待
                String contractId = String.valueOf(((Map<String, Object>) resultMap.get("responseData")).get("contractId"));
                logger.info("=======OPERATION_COMPLETE========contractId=========" + contractId);
                //现根据合同id查流程id，提交合同必生成预览后数据
                DataTable dataTable = SqlUtils.doQuery(String.format(QueryInstanceIdByContractId, contractId, "previewAfter"));
                if (dataTable.getRows().size() > 0) {
                    String instanceId = dataTable.getRows().get(0).getString(0);
                    logger.info("=======OPERATION_COMPLETE========instanceId=========" + instanceId);
                    InstanceData instanceData = new InstanceData(getEngine(), instanceId, User.AdministratorID);
                    // 获取状态 字段 更改
                    IInstanceDataItem item = instanceData.getItem("waitState");
                    if (item != null) {
                        item.setValue(1);
                    }
                    if (instanceData.Submit()) {
                        logger.info("==waitFinish====" + contractId + "-----" + instanceId);
                        return new ReturnVO<String>("0", "success for wait", null);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new ReturnVO<String>("1", "error", null);
    }

    /**
     * 下载合同
     *
     * @param instanceId
     * @param contractId
     * @param response
     * @return
     */
    @RequestMapping(value = "/downloadFile", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public Object downloadFile(String instanceId, String contractId, HttpServletResponse response) {
        try {
            Bestsign_file bestsignFile = apiController.downloadFileNoSave(instanceId, contractId, new DownloadFileVo(Arrays.asList(contractId)));
            response.setCharacterEncoding("UTF-8");
            response.setContentType(bestsignFile.getFileType());
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(bestsignFile.getFileName(), "UTF-8"));
            response.addHeader("Content-Type", bestsignFile.getFileType());
            response.flushBuffer();
            response.getOutputStream().write(bestsignFile.getContent());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 更改 合同id，避免 出现 shortString
     *
     * @param instanceId
     */
    @RequestMapping(value = "/updateContractId", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public void updateContractId(String instanceId) {
        Bestsign_file bestsignFile = APIController.queryFile(instanceId, "previewAfter");
        if (null != bestsignFile) {
            try {
                InstanceData instanceData = new InstanceData(getEngine(), instanceId, User.AdministratorID);
                // 获取状态 字段 更改
                IInstanceDataItem item = instanceData.getItem("ContractId");
                item.setValue(bestsignFile.getContractId());
                instanceData.Submit();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 复制流程
     *
     * @param instanceId
     */
    @RequestMapping(value = "/copyInstance", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    @ResponseBody
    public void copyInstance(String instanceId) {
        // 获取模板
        InstanceData instanceData = null;
        try {
            instanceData = new InstanceData(getEngine(), instanceId, User.AdministratorID);
            InstanceContext context = instanceData.getInstanceContext();

            PublishedWorkflowTemplate workflowTemplate = getEngine().getWorkflowManager().GetDefaultWorkflow(context.getWorkflowCode());
            BizObjectSchema schema = getEngine().getBizObjectManager().GetPublishedSchema(
                    workflowTemplate.getBizObjectSchemaCode());
            BizObject bo = new BizObject(getEngine().getOrganization(),
                    AppUtility.getEngine().getMetadataRepository(),
                    getEngine().getBizObjectManager(),
                    AppUtility.getEngine().getBizBus(),
                    schema,
                    User.AdministratorID,
                    OrganizationUnit.DefaultRootID);

            bo.Create(instanceData);

            // 创建流程实例
            String newInstanceId = getEngine().getInstanceManager().CreateInstance(
                    bo.getObjectID(),
                    workflowTemplate.getWorkflowCode(),
                    workflowTemplate.getWorkflowVersion(),
                    null,
                    null,
                    getUserValidator().getUserID(),
                    null,
                    false,
                    InstanceContext.UnspecifiedID,
                    null,
                    Token.UnspecifiedID);
            // 设置紧急程度为普通
            MessageEmergencyType emergencyType = MessageEmergencyType.Normal;
            Map<String, Object> paramTablesOld = instanceData.getBizObject().getValueTable();
            Map<String, Object> paramTables = new HashMap<>();
            for (String key : paramTablesOld.keySet()) {
                if (!BASEDTO.contains(key) && paramTablesOld.get(key) instanceof String) {
                    paramTables.put(key, paramTablesOld.get(key));
                }
            }

            // 启动流程的消息
            StartInstanceMessage startInstanceMessage = new StartInstanceMessage(
                    emergencyType,
                    newInstanceId,
                    null,
                    paramTables,
                    PriorityType.Normal,
                    false,
                    null,
                    false,
                    Token.UnspecifiedID,
                    null);
            getEngine().getInstanceManager().SendMessage(startInstanceMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 重置流程
     *
     * @param instanceId
     */
    @RequestMapping(value = "/resetInstance", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    @ResponseBody
    public void resetInstance(String instanceId) {
        // 获取模板
        InstanceData instanceData = null;
        try {
            instanceData = new InstanceData(getEngine(), instanceId, User.AdministratorID);
            InstanceContext context = instanceData.getInstanceContext();
            PublishedWorkflowTemplateHeader workflowTemplate = getEngine().getWorkflowManager().GetPublishedTemplateHeader(context.getWorkflowCode(), context.getWorkflowVersion());
            BizObject bo = instanceData.getBizObject();

            bo.Update(instanceData);

            MessageEmergencyType emergencyType = MessageEmergencyType.Normal;
            Map<String, Object> paramTables = instanceData.getBizObject().getValueTable();


            // 启动流程的消息
            StartInstanceMessage startInstanceMessage = new StartInstanceMessage(
                    emergencyType,
                    instanceId,
                    null,
                    paramTables,
                    PriorityType.Normal,
                    true,
                    null,
                    false,
                    Token.UnspecifiedID,
                    null);
            getEngine().getInstanceManager().SendMessage(startInstanceMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 激活流程
     *
     * @param instanceId
     */
    @RequestMapping(value = "/activeInstance", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    @ResponseBody
    public void activeInstance(String instanceId) throws Exception {
        ActivateInstanceMessage instanceMessage = new ActivateInstanceMessage(instanceId);
        getEngine().getInstanceManager().SendMessage(instanceMessage);
    }

    @RequestMapping(value = "/orgNames", produces = "application/json;charset=utf-8")
    @ResponseBody
    public RetResult getCompanyList() {
        Map<Object, Object> signType = redisUtil.hmget("signType");
        if (signType.size() == 0) {
            try {
                ArrayList<Map<String, Object>> arrayList = new ArrayList<>();
                Resource resource = new ClassPathResource("Company");
                File myFile = resource.getFile();
                ArrayList<Object> company = FileUtil.fileToArray(myFile);
                resource = new ClassPathResource("SignName");
                myFile = resource.getFile();
                ArrayList<Object> signName = FileUtil.fileToArray(myFile);

                for (int i = 0; i < company.size(); i++) {
                    Map<String, Object> map = new HashMap<>(4);
                    map.put("company", company.get(i).toString());
                    map.put("signName", signName.get(i));
                    arrayList.add(map);
                }
                return RetResponse.makeOKRsp(arrayList);
            } catch (IOException e) {
                return ErrorUtil.generalException(e);
            }
        }
        return RetResponse.makeOKRsp(signType);
    }
}
